#!/bin/sh

# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This script can maintain a log file across stateful partition wiping
# transition.

SCRIPT="$0"
CLOBBER_LOG_FILE="clobber.log"

# Temp folder is always accessible (by tmpfs), but stateful partition may be not
# available. To verify that, check the existence of STATEFUL_LOG_FOLDER.
STATEFUL_LOG_FOLDER="/mnt/stateful_partition/unencrypted/"
STATEFUL_LOG_PATH="$STATEFUL_LOG_FOLDER/$CLOBBER_LOG_FILE"
TMP_LOG_PATH="/tmp/$CLOBBER_LOG_FILE"
MAX_KEEP_LOG_LINES=512
BLOCK_DUMP_LINES=64

log_prefix() {
  echo "$(date --utc '+%Y/%m/%d %H:%M:%S') UTC"
}

preserve_log() {
  # Try to copy log from stateful partition to tmp.
  local source_path="$STATEFUL_LOG_PATH"
  local dest_path="$TMP_LOG_PATH"

  # TODO(hungte) store log in some special place, like last sector of stateful
  # partition so that logs won't be lost if user interrupts during wiping.

  if [ -s "$source_path" ]; then
    tail -n $MAX_KEEP_LOG_LINES "$source_path" >"$dest_path"
  fi
  echo "$(log_prefix) (preserve log): $@" >>"$dest_path"
}

restore_log() {
  # Try to copy log from tmp back to stateful partition.
  local source_path="$TMP_LOG_PATH"
  local dest_path="$STATEFUL_LOG_PATH"
  # the mode should be matched to chromeos_startup.
  mkdir -p -m 0755 "$STATEFUL_LOG_FOLDER"
  if [ -s "$source_path" ]; then
    cp "$source_path" "$dest_path"
  fi
  echo "$(log_prefix) (restore log): $@" >>"$dest_path"
}

find_log_path() {
  # Always use log in stateful partition, otherwise create in temp.
  local dest_path="$STATEFUL_LOG_PATH"
  if [ ! -d "$STATEFUL_LOG_FOLDER" ]; then
    dest_path="$TMP_LOG_PATH"
  fi
  echo "$dest_path"
}

append_log() {
  # Add one line of log into the clobber log file.
  local dest_path="$(find_log_path)"
  echo "$(log_prefix) $@" >>"$dest_path"
}

repair_log() {
  # Report detail messages for the status of stateful partition.
  local dest_path="$TMP_LOG_PATH"

  # TODO(hungte) try to recover logs from some where - see preserve_log.

  if [ ! -b "$1" ]; then
    echo "$(log_prefix) repair: $1: invalid device file." >>"$dest_path"
    return
  fi

  echo "$(log_prefix) (repair): $@" >>"$dest_path"
  # "fsck -n" and "mount -v" may also help.
  dumpe2fs -fh "$1" >>"$dest_path" 2>&1

  # try to dump first several blocks
  echo "-- File system $1 block data (gz+base64):" >>"$dest_path"
  dd if="$1" bs=1M count=1 | gzip -c | base64 |
    head -n $BLOCK_DUMP_LINES >>"$dest_path" 2>/dev/null
  echo "-- File system $1 block data dump complete." >>"$dest_path"
  # to read back the block data, extract to a file and do
  # cat block | base64 -d | gunzip -c -d > block.bin
}

# Process the very limited commands
case "$1" in
  --preserve )
    shift
    preserve_log "$@"
    ;;
  --restore )
    shift
    restore_log "$@"
    ;;
  --repair )
    shift
    repair_log "$@"
    ;;
  -- )
    shift
    append_log "$@"
    ;;
  * )
    append_log "$@"
    ;;
esac
